import axios from 'axios'
import app from '@/main.js'
import { requestConfig, requestFileConfig } from './config'
import { Loading, Message } from 'element-ui'
import utils from '@/js/lib/utils'
const service = axios.create(requestConfig)
const serviceFile = axios.create(requestFileConfig)
let loadingInstance
let loadingQueue = 0
let isRefreshing = false
// 重试队列，每一项将是一个待执行的函数形式
let requests = []
const showLoading = (loadingFlag = true) => {
	loadingQueue++
	if (!loadingFlag) {
		return false
	}
	loadingInstance = Loading.service({ fullscreen: true, background: '#3031330f' })
	loadingInstance.fxIsLoading = true
}
const hideLoading = () => {
	loadingQueue--
	if (loadingQueue <= 0 && loadingInstance) {
		loadingInstance.close()
		loadingInstance.fxIsLoading = false
	}
}
function refreshToken () {
	return new Promise(resolve => {
		app.vue.$fxApi('auth.refreshToken')({
			data: {
				token: window.localStorage.token
			}
		}).then(res => {
			return resolve(res)
		}).catch(res => {
			window.location.href = '/'
		})
		// return resolve('eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJhZG1pbiIsImNvZGUiOiIwMDAwMDAiLCJjcmVhdGVkIjoxNjEyNzY4ODMwNjI4LCJ0ZW5hbnRJZCI6MTAsIm5hbWUiOiLns7vnu5_nrqHnkIblkZgiLCJleHAiOjE2OTkxNjg4MzAsInVzZXJJZCI6MTAwMDAwMDAwMDAwMDAwMDB9.qiZhdIBiSv124HQfh3X3kGYWuF1aOHllwPD9D6TX7RtUb4tMZbucd4tXkQg3HBMI1b6gpbE9XUsNFcKvRz9uIw')
	})
}
const requestInterceptors = [
	config => {
		config.headers.Authorization = window.localStorage.token// app.vue.$store.state.loginer.token
		return config
	},
	error => {
		return Promise.reject(error)
	}
]
const responseInterceptors = [
	res => {
		hideLoading()
		if (res.data.resultCode) {
			return res.data || {}
		} else {
			const config = res.config
			if (res.data.code === 100004) {
				if (!isRefreshing) {
					isRefreshing = true
					return refreshToken().then(res => {
						const token = res.token
						// service.setToken(token)
						config.headers.Authorization = token
						window.localStorage.setItem('token', token)
						// config.baseURL = ''
						// 已经刷新了token，将所有队列中的请求进行重试
						requests.forEach(cb => cb(token))
						requests = []
						return service(config)
					// }).finally(() => {
					// 	isRefreshing = false
					}).finally(() => {
						isRefreshing = false
					})
				} else {
					// 正在刷新token，返回一个未执行resolve的promise
					return new Promise((resolve) => {
						// 将resolve放进队列，用一个函数形式来保存，等token刷新后直接执行
						requests.push((token) => {
							// config.baseURL = ''
							console.log(token)
							config.headers.Authorization = token
							resolve(service(config))
						})
					})
				} 			// return res
			} else if (res.data.code === 100003 || res.data.code === 100001 || res.data.code === 100002 || res.data.code === 100005 || res.data.code === 400000) {
				if (res.data.msg) {
					app.vue.$fxMessage.error(res.data.msg)
				}
				window.location.href = '/'
			} else {
				return Promise.reject(res.data)
			}
		}
	},
	error => {
		hideLoading()
		const serviceError = {
			code: 5000,
			message: '请求失败！'
		}
		if (error.response && error.response.data) {
			if (typeof error.response.data !== 'object' || error.response.status === 500) {
				return Promise.reject(serviceError)
			}
			// 刷新token
			// if (error.response.data.code === 100003 || error.response.data.code === 100004 || error.response.data.code === 100002) {
			// 	error.response.config.__isRetryRequest = true
			// 	error.response.config.headers.Authorization = 'eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJhZG1pbiIsImNvZGUiOiIwMDAwMDAiLCJjcmVhdGVkIjoxNjEyNzY4ODMwNjI4LCJ0ZW5hbnRJZCI6MTAsIm5hbWUiOiLns7vnu5_nrqHnkIblkZgiLCJleHAiOjE2OTkxNjg4MzAsInVzZXJJZCI6MTAwMDAwMDAwMDAwMDAwMDB9.qiZhdIBiSv124HQfh3X3kGYWuF1aOHllwPD9D6TX7RtUb4tMZbucd4tXkQg3HBMI1b6gpbE9XUsNFcKvRz9uIw'
			// 	return axios(error.response.config)
			// }
			return Promise.reject(error.response.data)
		} else {
			return Promise.reject(serviceError)
		}
	}
]
service.interceptors.request.use(...requestInterceptors)
serviceFile.interceptors.request.use(...requestInterceptors)
service.interceptors.response.use(...responseInterceptors)
serviceFile.interceptors.response.use(...responseInterceptors)
const errorToast = error => {
	return new Promise(resolve => {
		const msgOptions = {
			message: error.msg || 'has not error message',
			type: 'error',
			dangerouslyUseHTMLString: true,
			customClass: 'fx-message-error-class'
		}
		Message(msgOptions)
		resolve()
	})
}
const successToast = message => {
	return new Promise(resolve => {
		app.vue.$fxMessage.success(message)
		resolve()
	})
}
const failToast = message => {
	return new Promise(resolve => {
		app.vue.$fxMessage.error(message)
		resolve()
	})
}
const urlEncode = (obj) => {
	const params = []
	Object.keys(obj).forEach((key) => {
		let value = obj[key]
		if (typeof value === 'undefined') {
			value = ''
		}
		params.push([key, value].join('='))
	})
	return encodeURI(params.join('&'))
}
const requestCommon = (type) => {
	return ({ url, data, query = {}, loading = true, autoErrorMsg = true, autoSuccessMsg, responseComplete, success }) => {
		const requestInfo = app.vue.$fxLogger.requestInfoStart(url, data, query)
		showLoading(loading)
		return new Promise((resolve, reject) => {
			service({
				method: type,
				url: `${url}?${urlEncode(query)}`,
				data,
				// params: query,
				responseType: 'json'
			}).then(res => {
				if (autoSuccessMsg && res.msg && !res.batchFailFlag) {
					successToast(res.msg)
				}
				if (autoSuccessMsg && res.msg && res.batchFailFlag) {
					failToast(res.msg)
				}
				let _res = responseComplete ? res : (utils.isDef(res.data) ? res.data : {})
				if (success && typeof success === 'function') {
					_res = success(_res)
				}
				resolve(_res)
			}).catch((error) => {
				if (autoErrorMsg) {
					errorToast(error).then(() => {
						reject(error)
					})
				} else {
					reject(error)
				}
			}).always(() => {
				requestInfo.end(url)
			})
		})
	}
}
const requestFile = ({ url, data, query = {}, loading = true, autoErrorMsg = true, autoSuccessMsg, responseComplete, success }) => {
	const requestInfo = app.vue.$fxLogger.requestInfoStart(url, data, query)
	const params = new FormData()
	Object.keys(data).forEach(item => {
		params.append(item, data[item])
	})
	showLoading(loading)
	return new Promise((resolve, reject) => {
		serviceFile({
			method: 'post',
			url,
			data: params,
			// params: query,
			responseType: 'json'
		}).then(res => {
			if (autoSuccessMsg) {
				successToast(res.msg)
			}
			let _res = responseComplete ? res : (utils.isDef(res.data) ? res.data : {})
			if (success && typeof success === 'function') {
				_res = success(_res)
			}
			resolve(_res)
		}).catch((error) => {
			if (autoErrorMsg) {
				errorToast(error).then(() => {
					reject(error)
				})
			} else {
				if (error.msg) {
					failToast(error.msg).then(() => {
						reject(error)
					})
				} else {
					reject(error)
				}
			}
		}).always(() => {
			requestInfo.end(url)
		})
	})
}
export default {
	requestPost: requestCommon('post'),
	requestPut: requestCommon('put'),
	requestDel: requestCommon('delete'),
	requestGet: requestCommon('get'),
	requestPatch: requestCommon('patch'),
	requestFile
}
export const fxLoading = loadingInstance
